from django_redis import get_redis_connection
from rest_framework import serializers
from goods.models import SKU
from orders.models import OrderInfo, OrderGoods
from datetime import datetime
from decimal import Decimal
from django.db import transaction


class CartSKUSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = SKU
        fields = '__all__'


class OrderSettlementSerializer(serializers.Serializer):

    freight = serializers.DecimalField(max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


class SaveOrderSerializer(serializers.ModelSerializer):

    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs={
            'address':{
                'write_only': True,
                'required': True
            },
            'pay_method': {
                'write_only': True,
                'required': True
            },
        }

    def create(self, validated_data):
        # 获取用户数据
        user = self.context['request'].user
        # 获取支付方式和地址
        pay_method = validated_data['pay_method']
        address = validated_data['address']
        # 生产订单编号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S')+'%09d'%user.id

        with transaction.atomic():

            save_point = transaction.savepoint() # 生产保存点对象

            try:
                # 先初始化一个订单对象
                order = OrderInfo.objects.create(
                    order_id = order_id,
                    user = user,
                    address = address,
                    total_count = 0,
                    total_amount = Decimal(0),
                    freight = Decimal(10),
                    pay_method = pay_method,
                    status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == 2 else OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                # 获取商品对象
                conn = get_redis_connection('cart')
                # 从redis中获取数据
                sku_id_count = conn.hgetall('cart_%s' % user.id)
                # 获取选中状态数据
                cart_selected = conn.smembers('cart_selected_%s' % user.id)
                # 数据构建
                cart = {}
                for sku_id in cart_selected:
                    cart[int(sku_id)] = int(sku_id_count[sku_id])

                # 查询数据对象
                # skus = SKU.objects.filter(id__in=cart.keys())
                # 遍历商品对象
                for sku_id in cart.keys():
                    while True:
                        sku = SKU.objects.get(id = sku_id)
                        sku_count = cart[sku.id] # 获取购买商品数量

                        old_stock = sku.stock
                        old_sales = sku.sales
                        # 判断库存
                        if sku_count > old_stock:
                            raise serializers.ValidationError('库存不足')
                        # 修改商品库存和销量
                        new_stock = old_stock - sku_count
                        new_sales = old_sales + sku_count
                        ret = SKU.objects.filter(stock=old_stock).update(stock=new_stock, sales=new_sales)

                        if ret == 0:
                            continue


                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()

                        # 修改spu表的总销量
                        sku.goods.sales += sku_count
                        sku.goods.save()

                        # 修改order订单表
                        order.total_count += sku_count
                        order.total_amount += (sku.price*sku_count)
                        # 商品订单保存
                        OrderGoods.objects.create(
                            order = order,
                            sku = sku,
                            count = sku_count,
                            price = sku.price,
                        )

                        break

                # 总价添加
                order.total_amount += order.freight
                order.save()


            except:
                # 出错了 就回到保存点
                transaction.savepoint_rollback(save_point)
            else:
                # 没出错 就提交保存点下的所有数据库操作
                transaction.savepoint_commit(save_point)

                # 购物车redis商品删除
                conn.hdel('cart_%s'%user.id, *cart_selected)
                conn.srem('cart_selected_%s'%user.id, *cart_selected)
                # 返回订单对象

                return order